import { calcIntersectingLines } from "../../utils/linesUtils";
import { cloneDeep, debounce, getTextParams, UUID2 } from "../../utils/utils";
import { useStore } from "vuex";
import { readPageInfo, savePageInfo } from "../../service/page";
import dayjs from "dayjs";

const store = useStore();
const state = {
  // 图层列表面板
  selectedTree: true,
  // 组件库面板
  selectedLib: true,
  // 配置面板
  selectedConfig: true,
  // 设计面板(工具栏)
  selectToolBar: true,
  // 小地图
  selectCanvasMap: true,
  // 设计面板loading
  showContent: true,
  // 小地图面板
  selectedMap: true,
  // 对齐线
  editMode: false,
  screen: {
    id: 0,
    name: "",
  },
  pageConfig: {
    width: 1920,
    height: 1080,
    bgColor: "rgba(13, 42, 67, 0)",
    bgImage: "https://files.pengxiaotian.com/datav/bj.png",
    grid: 8,
    screenshot: "",
    zoomMode: 0,
    useWatermark: false,
    styleFilterParams: {
      enable: false,
      hue: 0,
      saturate: 100,
      brightness: 100,
      contrast: 100,
      opacity: 100,
    },
    flow: {},
    variables: {
      componentsView: {},
      publishersView: {},
      subscribersView: {},
    },
  },
  components: [],
  subComponents: [],
  canvas: {
    scale: 1,
    width: 1920,
    height: 1080,
  },
  referLine: {
    enable: true
  },
  guideLine: {
    h: [],
    v: []
  },
  alignLine: {
    enable: true,
    show: false,
    top: 0,
    bottom: 0,
    left: 0,
    right: 0,
    vertical: 0,
    horizontal: 0,
  },
  contextMenu: {
    show: false
  },
  isNormalResizeMode: true,
  snapshotIndex: -1, // 快照索引
  snapshotData: [], // 编辑器快照数据
  snapMaxLength: 50,
  pageInfo: {},
  pageFilters: [],
};

const getters = {
  selectedComp: (state) => {
    return state.components.find(m => m.selected);
  },
  getPanelOffsetX: (state) => {
    let offsetX = 0;
    if (state.selectedTree) {
      offsetX += 200;
    }

    if (state.selectedLib) {
      offsetX += 233;
    }

    if (state.selectedConfig) {
      offsetX += 332;
    }
    return offsetX;
  },
  getPanelOffsetY: (state) => {
    let offsetY = 0;
    if (state.selectToolBar) {
      offsetY += 40;
    }
    return offsetY;
  }
};
const mutations = {
  SET_SelectedTree(state) {
    state.selectedTree = !state.selectedTree;
  },
  SET_SelectedLib(state) {
    state.selectedLib = !state.selectedLib;
  },
  SET_SelectedConfig(state) {
    state.selectedConfig = !state.selectedConfig;
  },
  SET_SelectedToolBar(state) {
    state.selectToolBar = !state.selectToolBar;
  },
  SET_SelectedMap(state) {
    state.selectedMap = !state.selectedMap;
  },
  SET_ShowContent(state) {
    state.showContent = !state.showContent;
  },
  SET_SCREEN(state, screen) {
    state.screen = {
      id: screen.id,
      name: screen.name,
    };
  },
  SET_COMPONENTS(state, components) {
    const cons = [];
    const subComs = [];
    components.forEach(c => {
      if (c.type === "com") {
        cons.push(c);
      } else if (c.type === "subCom") {
        subComs.push(c);
      }
    });
    state.components = cons;
    state.subComponents = subComs;
  },
  SET_PAGECONFIG(state, pageConfig) {
    state.pageConfig = pageConfig;
  },
  SET_CANVAS(state, { scale, width, height }) {
    state.canvas = {
      scale,
      width,
      height,
    };
  },
  SET_EditorMode(state, mode) {
    state.editMode = mode;
  },
  SET_PAGEINFO(state, pageInfo) {
    state.pageInfo = pageInfo;
  },
  /**
   * 计算对齐线
   */
  calcAlignLine(state, com) {
    if (!state.alignLine.enable) {
      return;
    }
    const attr = calcIntersectingLines(com, state.components, state.canvas.scale);
    state.alignLine = { ...state.alignLine, ...attr, show: true };
  },
  /**
   * 选择原件
   * @param state
   * @param id
   */
  selectComp(state, id) {
    selectComp(state.components, id);
  },
  /**
   * 隐藏对齐线
   * @param state
   * @param id
   */
  hideAlignLine(state, id) {
    if (!state.alignLine.enable) {
      return;
    }
    if (state.alignLine.enable && state.alignLine.show) {
      state.alignLine.show = false;
      selectComp(state.components, id);
    }
  },
  /**
   * 修改层级
   * @param state
   * @param id
   * @param moveType
   */
  moveComp(state, { id, moveType }) {
    const i = findCompIndex(state.components, id);
    if (moveType === "up") {
      if (i + 1 < state.components.length) {
        state.components.splice(i + 1, 0, ...state.components.splice(i, 1));
      }
    } else if (moveType === "down") {
      if (i > 0) {
        state.components.splice(i - 1, 0, ...state.components.splice(i, 1));
      }
    } else if (moveType === "top") {
      if (i + 1 < state.components.length) {
        state.components.push(...state.components.splice(i, 1));
      }
    } else if (moveType === "bottom") {
      if (i > 0) {
        state.components.unshift(...state.components.splice(i, 1));
      }
    }
  },
  changeResizeMode(state, isNormal) {
    state.isNormalResizeMode = isNormal;
  },
  setPublishersView(state, { id, key, enable }) {
    const pv = state.pageConfig.variables.publishersView;
    const pvKey = Object.keys(pv);
    const allKeys = new Set([...key, ...pvKey]);
    allKeys.forEach(key => {
      if (enable) {
        if (!pvKey.includes(key)) {
          pv[key] = [id];
        } else if (!pv[key].includes(id)) {
          pv[key].push(id);
        }
      } else {
        if (pvKey.includes(key)) {
          pv[key] = pvKey.filter(m => m !== id);
        }
      }

      if (pv[key].length === 0) {
        delete pv[key];
      }
    });
  },
  setSubscribersView(state, { id, data }) {
    const sv = state.pageConfig.variables.subscribersView;
    const keys = getTextParams(data).map(m => m.substr(1));
    const svKeys = Object.keys(sv);
    const allKeys = new Set([...keys, ...svKeys]);
    for (const allKey of allKeys) {
      if (allKey.length > 0) {
        if (keys.length > 0) {
          if (!svKeys.includes(allKey)) {
            sv[allKey] = [id];
          } else if (!svKeys[allKey].includes(allKey)) {
            sv[allKey].push(id);
          } else if (!keys.includes(key)) {
            sv[allKey] = sv[allKey].filter(m => m !== id);
          }
        } else {
          if (svKeys.includes(allKey)) {
            sv[allKey] = sv[allKey].filter(m => m !== id);
          }
        }

        if (sv[key].length === 0) {
          delete sv[key];
        }
      }
    }
  },
  DELETE_COMP(state, com) {
    if (com.type === "com") {
      state.components.splice(findCompIndex(state.components, com.id), 1);
    } else {
      state.subComponents.splice(findCompIndex(state.subComponents, com.id), 1);
    }
  },
  CLEAR_COMP(state) {
    state.components = [];
    state.subComponents = [];
  },
  ADD_COMP(state, com) {
    state.components = [...state.components, com];
  },
  COPY_COMP(state, id) {
    const getNewComp = (com, parentId) => {
      const nComp = cloneDeep(com);
      nComp.id = UUID2(6);
      nComp.alias += "_copy";
      nComp.attr.x += 30;
      nComp.attr.y += 30;

      nComp.hovered = false;
      nComp.selected = false;
      nComp.renameing = false;

      nComp.parentId = parentId;

      for (const key in nComp.apiData) {
        nComp.apiData[key].id = UUID2(6);
        nComp.apiData[key].comId = nComp.id;
      }
      return nComp;
    };
    const oComp = findComp(state.components, id);
    if (oComp.id) {
      const nComp = getNewComp(oComp);
      const nSubComp = findComp(state.subComponents, oComp.id).map(m => getNewComp(m, nComp.id));
      state.components.push(nComp);
      state.subComponents.push(...nSubComp);
      selectComp(state.components, nComp.id);
    }
  },
  addSnapshot(state) {
    // 添加新的快照
    let index = state.snapshotIndex;
    let startIndex = 0;
    let length = state.snapshotData.length;
    if (!(index == length - 1 && length < state.snapMaxLength)) {
      startIndex = Math.max(index + 2 - state.snapMaxLength, 0);
      state.snapshotData = state.snapshotData.slice(startIndex, index + 1);
    }
    state.snapshotData.push(cloneDeep(state.pageConfig));
    state.snapshotIndex = state.snapshotData.length - 1;
  },

  // 撤销操作
  undoSnapshot(state) {
    if (state.snapshotIndex >= 0) {
      state.snapshotIndex--;
      // todo
      state.commit("setLayout", cloneDeep(state.snapshotData[state.snapshotIndex]));
    }
  },

  // 反撤销操作
  redoSnapshot(state) {
    if (state.snapshotIndex < state.snapshotData.length - 1) {
      state.snapshotIndex++;
      // todo
      state.commit("setLayout", cloneDeep(state.snapshotData[state.snapshotIndex]));
    }
  },
  CREATE_FILTER(state, pageFilter) {
    pageFilter.createAt = dayjs().format("YYYY-MM-DD HH:mm:ss");
    pageFilter.updateAt = pageFilter.createAt;
    pageFilter.id = UUID2(8);
    state.pageFilters.push(pageFilter);
    console.log(state.pageFilters);
  },
  UPDATE_FILTER(state, pageFilter) {
    const pf = state.pageFilters.find(m => m.id === pageFilter.id);
    Object.assign(pf, {
      name: pageFilter.name,
      code: pageFilter.code,
      origin: pageFilter.origin,
      updateAt: dayjs().format("YYYY-MM-DD HH:mm:ss"),
    });
  },
  UPDATE_FILTER_NAME(state, data) {
    const pf = state.pageFilters.find(m => m.id === data.id);
    Object.assign(pf, {
      name: data.name,
      updateAt: dayjs().format("YYYY-MM-DD HH:mm:ss"),
    });
  },
  DELETE_FILTER(state, id) {
    const pfIdx = state.pageFilters.findIndex(m => m.id === id);
    state.splice(pfIdx, 1);
  },
  setFilterOption(state, filters) {
    state.pageFilters = filters;
  },
};

const actions = {
  autoCanvasScale(state, { offsetX, offsetY }) {
    const resize = debounce(() => {
      const width = document.documentElement.clientWidth - offsetX;
      const height = document.documentElement.clientHeight - offsetY;

      const a = (width - 120) / state.state.pageConfig.width;
      const b = (height - 140) / state.state.pageConfig.height;
      let scale = parseFloat((a > b ? b : a).toFixed(6) * 100);
      state.dispatch("setCanvasScale", { scale, offsetX, offsetY });
    }, 200);
    window.onresize = resize;
    resize();
  },
  setCanvasScale(state, { scale, offsetX, offsetY }) {
    let width = document.documentElement.clientWidth - offsetX;
    let height = document.documentElement.clientHeight - 42 - 32 - offsetY;
    let canvasScale = Math.min(Math.max(scale, 10), 200) / 100;
    // 方便计算滚动条 和 标尺
    const deltaW = state.state.pageConfig.width * scale;
    const deltaH = state.state.pageConfig.height * scale;
    if (width < deltaW) {
      width = deltaW + 400;
    }

    if (height < deltaH) {
      height = deltaH + 400;
    }
    state.commit("SET_CANVAS", { scale: canvasScale, width, height });
  },
  async loadScreen(state, page_url) {
    return new Promise((resolve, reject) => {
      readPageInfo({ page_url }).then(res => {
        if (res.code === 0) {
          let json = JSON.parse(res.data.result);
          const { components = [], pageConfig = {}, pageInfo = {}, pageFilters = [] } = json;
          state.commit("SET_COMPONENTS", components);
          state.commit("SET_PAGECONFIG", pageConfig);
          state.commit("SET_PAGEINFO", pageInfo);
          state.commit("design/setFilterOption", pageFilters, { root: true });
          resolve(res);
        } else {
          reject(res);
        }
      });
    });
  },
  async saveScreen(state, page_url) {
    let json = {
      pageConfig: state.state.pageConfig,
      components: state.state.components,
      pageInfo: state.state.pageInfo,
      pageFilters: state.state.pageFilters
    };
    return new Promise((resolve, reject) => {
      savePageInfo({ page_url, json: JSON.stringify(json) }).then(res => {
        if (res.code === 0) {
          resolve(res);
        } else {
          reject(res);
        }
      });
    });
  },
  async loadComps(projectId) {
    try {
      // const res = await getComs(projectId)
      // if (res.data.code === 0) {
      //   this.commit("SET_COMS", res.data.data);
      // } else {
      //   throw Error(res.data.message)
      // }
    } catch (error) {
      throw error;
    }
  },
  async addCom(state, com) {
    try {
      state.commit("ADD_COMP", com);
    } catch (error) {
      throw error;
    }
  }
};

const findCompIndex = (comps, id) => {
  return comps.findIndex(c => c.id === id);
};

const findComp = (comps, id) => {
  return comps.find(c => c.id === id) || [];
};

const selectComp = (comps, id) => {
  comps.forEach(com => {
    if (com.id === id) {
      com.selected = true;
    } else {
      com.selected = false;
    }
    com.hovered = false;
  });
};

export default {
  namespaced: true,
  state,
  mutations,
  getters,
  actions
};
